/*
* File: CFdEventEpoll.h
* Copyright (c) 2010. Silviu Caragea <silviu@intelliproject.net>
* Created on September 15, 2010, 9:15 PM
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*  1.Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
*  2.Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the distribution.
*  3.All advertising materials mentioning features or use of this software
*    must display the following acknowledgement:
*       This product includes software developed by the University of
*       California, Berkeley and its contributors.
*  4.Neither the name of the University nor the names of its contributors
*    may be used to endorse or promote products derived from this software
*    without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED.IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/


#ifndef CFDEVENTEPOLL_H
#define	CFDEVENTEPOLL_H

#include "../IFdEventInterface.h"
#include "../../utils/CException.h"

#ifdef USE_EPOLL

#include <sys/epoll.h>

/*
    http://linux.die.net/man/7/epoll
    http://linux.die.net/man/2/epoll_wait
    http://linux.die.net/man/2/epoll_ctl
    http://linux.die.net/man/2/fcntl
*/

namespace litevent
{


const struct EventMothodSignature sigEpoll =
{
    "epoll",
    EnumEventHandlerTypeEpoll
};

class CFdEventEpoll :public IFdEventInterface
{    
public:    
    explicit CFdEventEpoll(size_t maxfds);
    ~CFdEventEpoll();

protected:
    int poll(int timeoutMs);
    int getEventRevent(size_t node);
    int getEventFileDescriptor(size_t node);   
    int setEvent(int fd_node , int fd, int events);
    int deleteEvent(int fd_node, int fd );
    int getEventNextFileDescriptor(int node);

private:
    int epollFd;
    struct epoll_event *epollEvents;
    DISALLOW_IMPLICIT_CONSTRUCTORS(CFdEventEpoll);
};

inline CFdEventEpoll::CFdEventEpoll(size_t maxfds):IFdEventInterface(maxfds)
{
        
    if (-1 == (this->epollFd = epoll_create(this->maxfds)))
    {
        util::CLogger::sharedLogger()->WriteFormated("%s.%d: CFdEventEpoll::CFdEventEpoll epoll_create failed: %s ", __FILE__, __LINE__,strerror(errno));
	throw util::CException("CFdEventEpoll::CFdEventEpoll epoll_create failed",1) ;
    }

    /*If the FD_CLOEXEC bit is 0, the file descriptor will remain open across an execve, otherwise it will be closed.*/

    if (-1 == fcntl(this->epollFd, F_SETFD, FD_CLOEXEC))
    {
        util::CLogger::sharedLogger()->WriteFormated("%s.%d: CFdEventEpoll::CFdEventEpoll fcntl failed: %s ", __FILE__, __LINE__,strerror(errno));
	close(this->epollFd);
	throw util::CException("CFdEventEpoll::CFdEventEpoll fcntl failed",2);
    }

    this->epollEvents = (epoll_event*)malloc(this->maxfds * sizeof(*this->epollEvents));
}

inline CFdEventEpoll::~CFdEventEpoll()
{
    if(this->epollFd != -1)
        close(this->epollFd);

    if(this->epollEvents)
        free(this->epollEvents);
}

}

#endif

#endif	/* CFDEVENTEPOLL_H */

